﻿//=====================================================
// Copyright © 2017-2018 xuxuzhaozhao
// All rights reserved
// GUID: 35fa78da-f094-418a-a96f-6bea1524d9ee
// CLR版本: 4.0.30319.42000
// 命名空间名称: xuxuzhaozhao.Blog.Infrastructure.XuTools
// 文件名: XuTools
// 当前系统时间: 2017/11/8 10:21:58
// 当前登录用户名: xuxuzhaozhao
//======================================================

using System;
using System.Linq;
using System.Linq.Expressions;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
using System.Linq.Dynamic;
using xuxuzhaozhao.Blog.Infrastructure.XuEntityFramework;

namespace xuxuzhaozhao.Blog.Infrastructure.XuTools
{
    public static class XuTools
    {
        /// <summary>
        /// 去掉字符串S首尾特定字符串R
        /// </summary>
        /// <param name="s">此字符串</param>
        /// <param name="r">需要排除的字符串R</param>
        /// <returns></returns>
        public static string Trim(this string s, string r)
        {
            if (string.IsNullOrEmpty(s)) return s;
            while (s.StartsWith(r))
            {
                s = s.Substring(r.Length);
            }
            while (s.EndsWith(r))
            {
                s = s.Substring(0, s.Length - r.Length);
            }
            return s;
        }

        /// <summary>
        /// 正则防止注入攻击(2017年10月9日，Axuzer)
        /// </summary>
        /// <param name="sql"></param>
        /// <returns></returns>
        public static string StripSql(this string sql)
        {
            if (string.IsNullOrEmpty(sql)) return sql;
            const string pattern1 = "(\\%27)|(\\')|(\\-\\-)";
            const string pattern2 = "((\\%27)|(\\'))\\s*((\\%6F)|o|(\\%4F))((\\%72)|r|(\\%52))";
            const string pattern3 = "\\s+exec(\\s|\\+)+(s|x)p\\w+";
            sql = Regex.Replace(sql, pattern1, string.Empty, RegexOptions.IgnoreCase);
            sql = Regex.Replace(sql, pattern2, string.Empty, RegexOptions.IgnoreCase);
            sql = Regex.Replace(sql, pattern3, string.Empty, RegexOptions.IgnoreCase);
            return sql;
        }

        /// <summary>
        /// 将decimal金额转为大写人民币(2017年10月9日，Axuzer)
        /// </summary>
        /// <param name="number"></param>
        /// <returns></returns>
        public static string ConvertToChinese(decimal number)
        {
            var s = number.ToString("#L#E#D#C#K#E#D#C#J#E#D#C#I#E#D#C#H#E#D#C#G#E#D#C#F#E#D#C#.0B0A");
            var d = Regex.Replace(s, @"((?<=-|^)[^1-9]*)|((?'z'0)[0A-E]*((?=[1-9])|(?'-z'(?=[F-L\.]|$))))|((?'b'[F-L])(?'z'0)[0A-L]*((?=[1-9])|(?'-z'(?=[\.]|$))))", "${b}${z}");
            var r = Regex.Replace(d, ".", m => "负元空零壹贰叁肆伍陆柒捌玖空空空空空空空分角拾佰仟万亿兆京垓秭穰"[m.Value[0] - '-'].ToString());
            if (r.EndsWith("元"))
                r += "整";
            return r;
        }

        /// <summary>
        /// md5,32位大写摘要算法
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public static string Md5Helper(string input)
        {
            var inputBytes = Encoding.UTF8.GetBytes(input);
            var md5 = new MD5CryptoServiceProvider();
            var md532 = BitConverter.ToString(md5.ComputeHash(inputBytes)).Replace("-", "").ToUpper();
            return md532;
        }

        /// <summary>
        /// 连接Lambda表达式
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="expr1"></param>
        /// <param name="expr2"></param>
        /// <returns></returns>
        public static Expression<Func<T, bool>> AndAlso<T>(this Expression<Func<T, bool>> expr1,
        Expression<Func<T, bool>> expr2)
        {
            var parameter = Expression.Parameter(typeof(T));

            var leftVisitor = new ReplaceExpressionVisitor(expr1.Parameters[0], parameter);
            var left = leftVisitor.Visit(expr1.Body);

            var rightVisitor = new ReplaceExpressionVisitor(expr2.Parameters[0], parameter);
            var right = rightVisitor.Visit(expr2.Body);

            return Expression.Lambda<Func<T, bool>>(
                Expression.AndAlso(left, right), parameter);
        }

        private class ReplaceExpressionVisitor
            : ExpressionVisitor
        {
            private readonly Expression _oldValue;
            private readonly Expression _newValue;

            public ReplaceExpressionVisitor(Expression oldValue, Expression newValue)
            {
                _oldValue = oldValue;
                _newValue = newValue;
            }

            public override Expression Visit(Expression node)
            {
                if (node == _oldValue)
                    return _newValue;
                return base.Visit(node);
            }
        }


        /// <summary>  
        /// 分页查询 + 条件查询 + 排序  
        /// </summary>  
        /// <typeparam name="T">泛型</typeparam>
        /// <param name="pageSize">每页大小</param>  
        /// <param name="pageIndex">当前页码</param>  
        /// <param name="total">总数量</param>  
        /// <param name="whereLambda">查询条件</param>  
        /// <param name="orderbyLambda">排序条件</param>  
        /// <returns>IQueryable 泛型集合</returns>  
        public static IQueryable<T> LoadPageItems<T>(int pageSize, int pageIndex, out int total,
            Expression<Func<T, bool>> whereLambda,
            string orderbyLambda) where T : class
        {
            using (var db = new XuxuzhaozhaoDbContext())
            {
                total = db.Set<T>().Where(whereLambda).Count();
                var temp = db.Set<T>().Where(whereLambda)
                             .OrderBy(orderbyLambda)
                             .Skip(pageSize * (pageIndex - 1))
                             .Take(pageSize);
                return temp.AsQueryable();
            }
        }
    }
}
